<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/*

/*
 * qq服务类
 * 这里从webqq登录->qq登录->收发消息->退出登录
 */

/**
 * Description of qq
 *
 * @author Administrator
 */
class Qq_service extends CLI_Controller{
    private $node_hash_service = true;//node 服务中 计算获得好友列表中 哈希服务的状态  true为服务已经开启 flash为关闭
    private $speak_service = true;//bot的语言服务是否已经开启
    private $sms_service = true;// 短信服务是否开启
    private $get_friend_information_lock;//获得朋友信息锁  如果为flash 那么就是获得好友列表失败
    private $qq;
    public function __construct() {
        parent::__construct();
        $this->qq = new stdClass();
        $this->load->helper('qq');
        $this->load->model('qq_chats_model');
	$this->load->config('node',true);
    }

    public function index()
    {
        $this->_qq_init();//初始化环境
        $this->_login_qq();//登陆qq
        $this->_group_list();//获得群列表
        $this->_friend_list();//获得好友列表
	
        CLI_FUN::echo_system("开始读取qq消息");
        /**为 群信息 好友信息 创建存储变量**/
        $this->qq->group_user_info = new stdClass;
        $this->qq->friend_data = new stdClass;
        while(TRUE)
        {
                $d = QQ::poll($this->qq->login->result->psessionid, $this->qq->clientid);
                $msg = json_decode($d);
                if ($msg->retcode === 0)
                {
                        foreach ($msg->result as $v)
                        {
                                if ($v->poll_type == "message")
                                {
                                    if(!isset($friend_data->{$v->value->from_uin}))
                                    {
                                        $friend_data = $this->_friend_data($v,$this->qq->cookie,$this->qq->friend_list_info);
                                    }
                                    $group_message_msg = '';
                                    $_record = $v->value;
                                    $this->_record($_record,"message");
                                    //处理消息
                                    foreach ($v->value->content as $t_id => $t_value)
                                    {
					if($t_id == '0')
					{
                                            continue;
					}
                                        if(!is_array($t_value))
					{
                                            $group_message_msg .= $t_value;
					}
					else
					{
                                            if($t_value->{0} == 'face') //是qq表情
                                            {
                                                    $group_message_msg .= "\{face:{$t_value->{1}}\}";
                                            }
                                            elseif($t_value->{0} == 'offpic')//是自定义表情
                                            {
                                                if($t_value->{1}->success == '1')
                                                {
                                                    $group_message_msg .= "\{offpic:{$t_value->{1}->file_path}\}";
                                                }
                                                else
                                                {
                                                    $group_message_msg .= "\{offpic:error\}";
                                                }
                                            }
					}
                                    }
                                    /*******获得回复内容******/
                                    $t_msg = $this->message_msg($group_message_msg,$v->value->from_uin);
                                    /*******回复信息******/
                                    QQ::send_buddy_msg($v->value->from_uin, $t_msg, $this->qq->login->result->psessionid, $this->qq->clientid);
                                    $db_msg_data = json_encode(array('msg'=>$group_message_msg,'date'=>time()));

                                    $t_name = isset($friend_data->{$v->value->from_uin}->nick)?$friend_data->{$v->value->from_uin}->nick:'未知';
                                    CLI_FUN::echos($t_name.'发来信息:'.$group_message_msg.'------回复---:'.$t_msg);
                                    continue;
                                }
                                
                                // 针对群
                                if ($v->poll_type == "group_message")
                                {
					$_record = $v->value;
                                        $group_message_msg = '';
					$this->_record($_record,"group_message");
                                        if(!isset($group_user_info->{$v->value->from_uin}))
                                        {
                                            $group_user_info->{$v->value->from_uin} = $this->_group_data($v,$this->qq->group_code,$this->qq->cookie,$this->qq->qqlogin);
                                        }

                                        // 处理简单表情
                                        foreach ($v->value->content as $font_face_string)
                                        {
                                            if(!is_array($font_face_string))
                                            {
                                                $group_message_msg .= $font_face_string;
                                            }
                                        }
                                        $t_msg = $this->group_message_msg($group_message_msg,$v->value->from_uin);
                                        if($t_msg != false)
                                        {
                                            QQ::send_qun_msg($v->value->from_uin, $t_msg, $this->qq->login->result->psessionid, $this->qq->clientid);
                                        }
                                        $t_msg = ($t_msg === false)?'未回复':$t_msg;
                                        $group_name = isset($qq_group_list->{$v->value->from_uin})?$qq_group_list->{$v->value->from_uin}:'未知群';

                                        $msg_info_user = isset($group_user_info->{$v->value->from_uin}->cards->{$v->value->send_uin})?
                                        $group_user_info->{$v->value->from_uin}->cards->{$v->value->send_uin}:
                                        $group_user_info->{$v->value->from_uin}->minfo->{$v->value->send_uin}->nick;

                                        CLI_FUN::echos('群【'.$group_name.'】-【'.$msg_info_user.'】发来信息:【'.$group_message_msg.'】回复:【'.$t_msg.'】');
                                        continue;
                                }


								// 如果是发送文件
                                if ($v->poll_type == "file_message")
                                {
                                        /****
                                Array
                                        (
                                                [retcode] => 0
                                                [result] => Array
                                                        (
                                                                [0] => Array
                                                                        (
                                                                                [poll_type] => file_message
                                                                                [value] => Array
                                                                                        (
                                                                                                [msg_id] => 26202
                                                                                                [mode] => recv
                                                                                                [from_uin] => 352783720
                                                                                                [to_uin] => 1292177349
                                                                                                [msg_id2] => 346793
                                                                                                [msg_type] => 9
                                                                                                [reply_ip] => 176884837
                                                                                                [type] => 101
                                                                                                [name] => 同城二手物品交易.docx
                                                                                                [time] => 1387468872
                                                                                                [session_id] => 4969
                                                                                                [inet_ip] => 1943023232
                                                                                        )

                                                                        )

                                                        )

                                        )
                                        file_messageArray
                                        (
                                                [retcode] => 102
                                                [errmsg] =>
                                        )
                                        Array
                                        (
                                                [retcode] => 0
                                                [result] => Array
                                                        (
                                                                [0] => Array
                                                                        (
                                                                                [poll_type] => file_message
                                                                                [value] => Array
                                                                                        (
                                                                                                [msg_id] => 26204
                                                                                                [mode] => refuse
                                                                                                [from_uin] => 352783720
                                                                                                [to_uin] => 1292177349
                                                                                                [msg_id2] => 462180
                                                                                                [reply_ip] => 176884837
                                                                                                [type] => 101
                                                                                                [session_id] => 4969
                                                                                                [cancel_type] => 1
                                                                                                [time] => 1387468960
                                                                                        )

                                                                        )

                                                        )

                                        )
                                        */
										continue;
                                }
                        }
                }

                if ($msg->retcode == 121)
                {
                        exit("退出");
                }
        }
    }
    
    /*
     * 登陆qq
     * return void
     */
    protected function _login_qq()
    {
        $qq_num = CLI_FUN::scanf('请输入您的qq号:');
	$passwd = CLI_FUN::scanf('请输入您的qq密码:');
        
        CLI_FUN::echo_system("开始登录qq");
        $verify = QQ::check_verify($qq_num);
        if (is_array($verify) && $verify[0] == 0)
        {
            CLI_FUN::echo_system("装载验证码成功");
	    $this->qq->verify = $verify[1];
        }
        else
        {
            QQ::check_verify_getimage($qq_num);
            $this->qq->verify = CLI_FUN::scanf('需要输入验证码:');
        }
        
        //生成密码
        $passwd = QQ::jspassword($verify[2],$passwd,  $this->qq->verify);
        //登录  这里是登录webqq网页  而不是登录webqq中的 qq系统
        $login = QQ::login($qq_num , $passwd, $this->qq->verify);
        if (is_array($login) && $login['4'] == "登录成功！")
        {
                CLI_FUN::echo_system("初次登陆成功:".$login['5']);
        }
        elseif (isset($login[4]))
        {
                CLI_FUN::echo_error("初次登陆失败:".$login[4]);
                exit();
        }
        else
        {
            
                CLI_FUN::echo_error("初次登陆失败,未知的错误");
                print_r($login);
                exit();
        }
        QQ::p_skey($login['2']);
         
        // 获取cookie信息
        $this->qq->cookie = json_decode(json_encode(QQ::get_cookie()));
        // 生成客户端id
        $this->qq->clientid = mt_rand(50888888,80888888);
        // 真正的上线 这里才是真的登录web qq中的qq
        $this->qq->login = json_decode(QQ::login2($this->qq->cookie->ptwebqq, $this->qq->clientid));

        if (!empty($this->qq->login) and $this->qq->login->retcode == 0)
        {
            $this->qq->number = $qq_num;
            CLI_FUN::echo_system("已成功上线");
        }
        else
        {
            CLI_FUN::echo_error("登陆失败,可能原因：vfwebqq参值不正确");
            print_r($this->qq->cookie);
            exit("0");
        }
    }
    
    /*
     * 获得群列表
     * return void
     */
    protected function _group_list()
    {
        CLI_FUN::echo_system("开始获得群列表信息");
        //echo $this->qq->login->result->vfwebqq,"\n",$this->qq->number,"\n",$this->qq->cookie->ptwebqq,"\n";
        /***获得群列表**/
        if(!isset($this->qq->login->result->vfwebqq))
        {
            print_r($this->qq);
            echo "\n\n\n\n\n";
            print_r($this->qq->login);
            exit('login error');
        }
        $t = QQ::get_group_name_list_mask(
                $this->qq->login->result->vfwebqq,
                $this->qq->number,
                $this->qq->cookie->ptwebqq
                );
        $qq_group = json_decode($t);

        $this->qq->group_list = new stdClass;
	$this->qq->group_code = new stdClass;
	$this->qq->group_flag = new stdClass;
        if($qq_group->retcode == '0')
        {
            foreach($qq_group->result->gnamelist as $item)
            {
                $this->qq->group_list->{$item->gid} = $item->name;
                $this->qq->group_code->{$item->gid} = $item->code;
                $this->qq->group_flag->{$item->gid} = $item->flag;
            }
            CLI_FUN::echo_system("群列表信息获取完成");
        }
        else
        {
            CLI_FUN::echo_error("群列表信息获取失败");
        }
        
    }
    
    /*
     * 获得好友列表
     * return void
     */
    protected function _friend_list()
    {
        CLI_FUN::echo_system("开始获得好友列表状态");
        /********获得好友列表状态   如果获得好友列表失败   那么在下面聊天的时候 也不会获得好友的详细信息******/
        $this->get_friend_information_lock = false;
        if($this->node_hash_service)
        {
            //获得好友列表
            $this->qq->friend_list = json_decode(QQ::get_user_friend($this->qq->login->result->vfwebqq,$this->qq->number,$this->qq->cookie->ptwebqq));
            if($this->qq->friend_list->retcode != 0)
            {
                CLI_FUN::echo_error("好友列表获取失败");
                CLI_FUN::echo_error($this->qq->friend_list);
            }
            else
            {
                CLI_FUN::echo_system("好友列表获取成功");
                $friend_data = new stdClass;
                $this->get_friend_information_lock = true;
                foreach($this->qq->friend_list->result->info as $item)
                {
                    $this->qq->friend_list_info->{$item->uin} = $item->nick;
                }
            }
            print_r($this->qq->friend_list_info);
        }
        else
        {
            CLI_FUN::echo_error("取消好友列表的获取,因为服务必须的服务为关闭状态");
        }
    }
    /*
     * 记录qq消息
     *
     *
     */
    private function _record($value,$type)
    {
	$this->qq_chats_model->add($value->msg_id,$value->from_uin,$value->to_uin,$value->msg_id2,$value->msg_type,$value->reply_ip,$value->time,var_export($value->content,true),$type);
    }
    /*
     * 获得回复的语句
     * 注意:这里的qq 不是qq号码  而是qq的uin值
     */
    public  function message_msg($content,$qq)
    {
        static $sms_qq = array();
        static $sms_count = array();
        if(isset($sms_qq[$qq]) && $sms_qq[$qq] == true) //判断是否需要发送短信
        {
            Socket_post::sms($content);
            $sms_count[$qq] = isset($sms_count[$qq])?$sms_count[$qq]++:1;
            $sms_qq[$qq] = false;
            return '短信已经发送了哦,您还有什么事情吗';
        }
        /* * 特定的处理方法 * */
        if(1 == $content)
        {
            if($this->sms_service)
            {
				$sms_qq[$qq] = true;
				return '好了现在输入您要给我主人发送的短信信息吧,我会帮你发送的';
				// return '额 短信接口暂停服务了';
            }
            else
            {
                return '啊哦 主人好像不想被打扰 把短信服务给关闭了';
            }
        }
        else if(2 == $content)
        {
            
        }
        if($this->speak_service)
        {
            return Socket_post::speak($content, 'QQ_'.$qq);
        }
        else
        {
            return '主人把我的说话功能关了 我不知道怎么回答你啊';
        }
    }
    
    /*
     * 获得群回复的语句
     */
    protected function group_message_msg($content,$qq)
    {
        if(preg_match('|seven::|', $content))
        {
            return Socket_post::speak($content, 'QQ_'.$qq);
        }
        else
        {
            return false;
        }
    }
    
    /*
     * 获得好友详细信息
     *
     */
    private function _friend_data($v,$cookie,$friend_list_info)
    {
            //////////////////////////////******获得发信息qq的详细信息**********////////////////
            $t =  json_decode(QQ::get_friend_data_qq($v->value->from_uin,$this->qq->login->result->vfwebqq)); //获得qq信息
            if($this->get_friend_information_lock !== false)
            {
                    $get_friend_information =  json_decode(QQ::get_friend_information($v->value->from_uin,$this->qq->login->result->vfwebqq)); //获得个人资料
            }

            /****************获得qq资料*********************/
            $t_qq_number = json_decode(QQ::get_friend_qq($v->value->from_uin,$this->qq->login->result->vfwebqq)); 
            $friend_data->{$v->value->from_uin} = new stdClass;
            if($t_qq_number->retcode === 0){
                    $friend_data->{$v->value->from_uin}->qq = $t_qq_number->result->account; //qq号码
            }
            else
            {
                    CLI_FUN::cli_echo("获得qq号失败");
            }
            if($t->retcode === 0){
                    $friend_data->{$v->value->from_uin}->level = $t->result->level; //qq等级
                    $friend_data->{$v->value->from_uin}->days = $t->result->days; //qq使用时间
                    $friend_data->{$v->value->from_uin}->nick =  $friend_list_info->{$v->value->from_uin}; //qq昵称
                    $friend_data->{$v->value->from_uin}->tuin =  $t->result->tuin;
            }
            else
            {
                    CLI_FUN::cli_echo("获得qq资料失败");
            }
            if($get_friend_information->retcode === 0){
                    $friend_data->{$v->value->from_uin}->blood =  $get_friend_information->result->blood;
                    $friend_data->{$v->value->from_uin}->city =  $get_friend_information->result->city;
                    $friend_data->{$v->value->from_uin}->college =  $get_friend_information->result->college;
                    $friend_data->{$v->value->from_uin}->constel =  $get_friend_information->result->constel;
                    $friend_data->{$v->value->from_uin}->country =  $get_friend_information->result->country;
                    $friend_data->{$v->value->from_uin}->email =  $get_friend_information->result->email;
                    $friend_data->{$v->value->from_uin}->face =  $get_friend_information->result->face;
                    $friend_data->{$v->value->from_uin}->gender =  $get_friend_information->result->gender;
                    $friend_data->{$v->value->from_uin}->homepage =  $get_friend_information->result->homepage;
                    $friend_data->{$v->value->from_uin}->mobile =  $get_friend_information->result->mobile;
                    $friend_data->{$v->value->from_uin}->occupation =  $get_friend_information->result->occupation;
                    $friend_data->{$v->value->from_uin}->personal =  $get_friend_information->result->personal;
                    $friend_data->{$v->value->from_uin}->phone =  $get_friend_information->result->phone;
                    $friend_data->{$v->value->from_uin}->province =  $get_friend_information->result->province;
                    $friend_data->{$v->value->from_uin}->shengxiao =  $get_friend_information->result->shengxiao;
                    $friend_data->{$v->value->from_uin}->stat =  $get_friend_information->result->stat;
                    $friend_data->{$v->value->from_uin}->vip_info =  $get_friend_information->result->vip_info;
            }
            else
            {
                    CLI_FUN::echo_error("获得个人资料失败");
                    $this->get_friend_information_lock = false;
            }
            return $friend_data;
    }

	/*
	 * 获得群成员列表
	 *
	 *
	 */

	protected function _group_data($v,$qq_group_code,$cookie,$login)
	{
		$group_user_info = json_decode(QQ::get_group_info_ext($qq_group_code->{$v->value->from_uin},$this->qq->login->result->vfwebqq));
		$group_user_info_detailed = new stdClass;
		$group_user_info_detailed->ginfo = $group_user_info->result->ginfo;
		if($group_user_info->retcode == 0)
		{
		    foreach($group_user_info->result->minfo as $item)
		    {
				$item = (object)$item;
		        $group_user_info_detailed->minfo->{$item->uin} = (object)$item;
		    }
		    foreach($group_user_info->result->vipinfo as $item)
		    {
		        $group_user_info_detailed->vipinfo = $item;
		    }
		    if(isset($group_user_info->result->cards)) //群备注
		    {
		        foreach($group_user_info->result->cards as $item)
		        {
		            $group_user_info_detailed->cards->{$item->muin} = $item->card;
		            if($item->muin == $login->result->uin)
		            {
		                $group_user_info_detailed->card = $item->card;
		            }
		        }
		    }
		}
		else
		{
			return false;
		}
		return $group_user_info_detailed;
	}
    /*
     * 初始化网络环境
     */
    protected function _qq_init() {
        return true;
        /***********************************************************************************************************************/
        CLI_FUN::echo_system("初始化环境");
        ///检查qq服务器是否可以连接
        CLI_FUN::echo_system("检测qq服务器是否可以连接");
        $qq_server_network = $this->_server_network('web2.qq.com', '80');
        if($qq_server_network === 0)
        {
            CLI_FUN::echo_error("qq服务器连接失败,是否忽略,这可能不是您的网络原因");
             $t = CLI_FUN::scanf('');
            if(trim($t) == 'N')
            {
                CLI_FUN::echo_error("程序关闭");
                exit;
            }
        }
        elseif($qq_server_network === 1)
        {
            CLI_FUN::echo_system("qq服务器连接成功,网络情况良好");
        }
        elseif($qq_server_network === 2)
        {
            CLI_FUN::echo_warning("qq服务器连接成功,网络连接有点慢");
        }
        
		/***********************************************************************************************************************/
		//检查node中的p参数计算服务是否已经开启
        CLI_FUN::echo_system("检查node中的p参数计算服务是否已经开启");
        $qq_server_network = $this->_server_network($this->config->item('p_ip','node'), $this->config->item('p_port','node'));
        if($qq_server_network === 0)
        {
            CLI_FUN::echo_error("node中的p参数计算服务是必须的,您必须开启它");
            exit;
            $this->node_hash_service = false;
        }
		/***********************************************************************************************************************/
        //检查node中的hash计算服务是否已经开启
        CLI_FUN::echo_system("检查node中的hash计算服务是否已经开启");
        $qq_server_network = $this->_server_network($this->config->item('h_ip','node'), $this->config->item('h_port','node'));
        if($qq_server_network === 0)
        {
            CLI_FUN::echo_warning("node hash服务检测失败,这会导致好友列表获取失败,是否忽略继续执行:(Y/N)",'');
            $t = CLI_FUN::scanf('');
            if(trim($t) == 'N')
            {
                CLI_FUN::echo_error("程序关闭");
                exit;
            }
            $this->node_hash_service = false;
        }
        elseif($qq_server_network === 1)
        {
            CLI_FUN::echo_system("node hash服务器连接成功,网络情况良好");
        }
        elseif($qq_server_network === 2)
        {
            CLI_FUN::echo_warning("node hash服务器连接成功,网络连接有点慢");
        }
        
		/***********************************************************************************************************************/
        //检查电脑的语言交流系统是否已经开启
        CLI_FUN::echo_system("检查电脑的语言交流系统是否已经开启");
        $this->load->config('speak',true);
        $qq_server_network = $this->_server_network($this->config->item('speak_service_ip','speak'), $this->config->item('speak_service_port','speak'));
        if($qq_server_network === 0)
        {
            CLI_FUN::echo_warning("语言交流系统服务器开启失败，正在尝试启动,请耐心等待三秒");
            
            $common = 'nohup php index.php speak_service service  > speak.log 2>&1 &';
            CLI_FUN::echo_warning(system($common));
            if(0 === $this->_server_network($this->config->item('speak_service_ip','speak'), $this->config->item('speak_service_port','speak')))
            {
                CLI_FUN::echo_warning("尝试启动失败,你看可以选择是否忽略继续执行:(Y/N)",'');
                $t = CLI_FUN::scanf('');
                if(trim($t) == 'N')
                {
                    CLI_FUN::echo_error("程序关闭");
                    exit;
                }
                $this->speak_service = false;
            }
            else
            {
                CLI_FUN::echo_warning("语言交流尝试启动成功");
            }
        }
        elseif($qq_server_network === 1)
        {
            CLI_FUN::echo_system("语言交流系统服务器连接成功,网络情况良好");
        }
        elseif($qq_server_network === 2)
        {
            CLI_FUN::echo_warning("语言交流系统服务器连接成功,网络连接有点慢");
        }
        
		/***********************************************************************************************************************/
        //检查短信服务是否已经开启
        CLI_FUN::echo_system("检查短信服务是否已经开启");
        $this->load->config('sms',true);
        $qq_server_network = $this->_server_network($this->config->item('sms_service_ip','sms'), $this->config->item('sms_service_port','sms'));
        if($qq_server_network === 0)
        {
            CLI_FUN::echo_warning("短信系统服务器开启失败，正在尝试启动,请耐心等待三秒");
            CLI_FUN::echo_warning(system('nohup php index.php  sms_service service  > sms.log 2>&1 &'));
            if(0 === $this->_server_network($this->config->item('sms_service_ip','sms'), $this->config->item('sms_service_port','sms')))
            {
                CLI_FUN::echo_warning("尝试启动失败,你看可以选择是否忽略继续执行:(Y/N)",'');
                $t = CLI_FUN::scanf('');
                if(trim($t) == 'N')
                {
                    CLI_FUN::echo_error("程序关闭");
                    exit;
                }
                $this->sms_service = false;
            }
            else
            {
                CLI_FUN::echo_warning("短信系统尝试启动成功");
            }
        }
        elseif($qq_server_network === 1)
        {
            CLI_FUN::echo_system("短信交流系统服务器连接成功,网络情况良好");
        }
        elseif($qq_server_network === 2)
        {
            CLI_FUN::echo_warning("短信交流系统服务器连接成功,网络连接有点慢");
        }
        CLI_FUN::echo_system("检测成功开始登录qq程序");
		/***********************************************************************************************************************/
    }
    
    /*
     * 检测服务器网络是否可以连接
     * return  0:连接失败   1:连接成功网络状态良好 2:连接成功 ping值偏大
     */
    protected function _server_network($url,$port=80)
    {
        $ping_time = 0;
        $ping_count = 3; //ping的次数
        for($i=0;$i<$ping_count;$i++)
        {
            $t = ping($url,$port);
            if(false == $t)
            {
                return 0;
                break;
            }
            $ping_time += $t;
        }
        $ping = ceil($ping_count/$ping_time);
        if($ping < 20)
        {
            return 1;
        }
        else
        {
            return 2;
        }
    }
}
